package test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;


// 2字节长度域
// 11字节头
// N字节Body
// 8字节MAC

public class ChinaUmsZjMessage {
	private HashMap<Integer, TLV> MsgMapReq = null;
	private HashMap<Integer, TLV> MsgMapRes = null;
	private String macValue;
	private int totallen = 0;
	
	public ChinaUmsZjMessage() {
		MsgMapReq = new LinkedHashMap<Integer, TLV>();
		MsgMapRes = new LinkedHashMap<Integer, TLV>();
	}
	
	public void AddBody(TLV tlvvalue) throws IOException {
		MsgMapReq.put(tlvvalue.getTag(), tlvvalue);
	}
	
	public void parseResponseByte(byte[] response, boolean isSignIn) throws Exception {
		
		int index = 0;
		subBytes(response, index, 13);
		index += 13;
		int msglen = 0;
		if ( isSignIn ) {
			msglen = response.length;
		} else {
			msglen = response.length - 8;
		}
		while(index < msglen) {
			byte[] tag = subBytes(response, index, 1);
			index += 1;
			int tagbitlen = 1;
			if ( (byte)(tag[0] & 0x80) != 0 ) {
				tagbitlen = 2;
			}
			boolean isCompressed = true;
			if ( (byte)(tag[0] & 0x40) == 0 ) {
				isCompressed = false;
			}
			
			int tag1 = (byte)(tag[0] & 0x3F);
			
			byte[] taglenbytes = subBytes(response, index, tagbitlen);
			index += tagbitlen;
			int taglen = byteArrayToInt(taglenbytes);
			
			byte[] valuebytes = subBytes(response, index, taglen);
			
			index += taglen;
			String value = null;
			
			if (isCompressed) {
				value = BcdCodeUtil.cbcd2string(valuebytes);
				MsgMapRes.put(tag1, new TLV(tag1, value, TLV.MetaType.C));
			} else {
				if ( tag1 == 61 ) {
					MsgMapRes.put(tag1, new TLV(tag1, valuebytes, TLV.MetaType.B));
				} else {
					MsgMapRes.put(tag1, new TLV(tag1, new String(valuebytes, "GBK"), TLV.MetaType.C));
				}
			}
		}
		
		byte[] mac = subBytes(response, index, 8);
		macValue = BitConvert.Hex2Str(mac);
	}
	
	public static byte[] subBytes(byte[] src, int offset, int count) {
		byte[] ret = new byte[count];
		for (int i = offset; i < offset + count; i++)
			ret[i - offset] = src[i];
		
		return ret;
	}
	
	public static int byteArrayToInt(byte[] b) {
	    int value = 0;
	    for (int i = b.length; i > 0; i--) {
	        int shift = ( b.length - i ) * 8;
	        value += (b[i - 1] & 0x000000FF) << shift;
	    }
	    return value;
	}
	
	public byte[] getSerialization(String macValue) throws Exception {
		
		ByteArrayOutputStream bodyOutStream = new ByteArrayOutputStream();
		ByteArrayOutputStream msgOutStream = new ByteArrayOutputStream();
		for (Map.Entry<Integer, TLV> entry : MsgMapReq.entrySet()) {
			bodyOutStream.write(entry.getValue().getByteData());
		}
		
		int totalnum = 11 + bodyOutStream.toByteArray().length + 8;
		byte[] lenbyte = new byte[2];
		lenbyte[0] = (byte) ((totalnum >> 8) & 0xFF);
		lenbyte[1] = (byte) ((totalnum) & 0xFF);
		
		msgOutStream.write(lenbyte);
		msgOutStream.write(UmsNacHead.getBytesArray());
		msgOutStream.write(bodyOutStream.toByteArray());
		
		if (macValue != null) {
			byte[] macBytes = BitConvert.Str2Hex(macValue);
			msgOutStream.write(macBytes);
		}
		
		
		bodyOutStream.close();
		msgOutStream.close();
		return msgOutStream.toByteArray();
	}
	
	public byte[] getBodyBytes() throws IOException {
		ByteArrayOutputStream bodyOutStream = new ByteArrayOutputStream();
		for (Map.Entry<Integer, TLV> entry : MsgMapReq.entrySet()) {
			bodyOutStream.write(entry.getValue().getByteData());
		}
		
		bodyOutStream.close();
		
		return bodyOutStream.toByteArray();
	}

	/**
	 * @return the totallen
	 */
	public int getTotallen() {
		//Iterator<Integer, TLV> it =
		return totallen;
	}

	/**
	 * @param totallen the totallen to set
	 */
	public void setTotallen(int totallen) {
		this.totallen = totallen;
	}
	

	public HashMap<Integer, TLV> getMsgMapRes() {
		return MsgMapRes;
	}

	public void setMsgMapRes(HashMap<Integer, TLV> msgMapRes) {
		MsgMapRes = msgMapRes;
	}

	public String getMacValue() {
		return macValue;
	}

	public void setMacValue(String macValue) {
		this.macValue = macValue;
	}
	
	public HashMap<Integer, TLV> getMsgMapReq() {
		return MsgMapReq;
	}

	public void setMsgMap(HashMap<Integer, TLV> msgMapReq) {
		MsgMapReq = msgMapReq;
	}
	
	public static void main(String args[]) throws Exception {
		System.out.println( System.getProperty("file.encoding") ); 
		ChinaUmsZjMessage msg = new ChinaUmsZjMessage();
		//String res = "00806000130000343030300004000230300108C7A9B5BDB3C9B9A6020131030438323130440720160415130002450920160415130002157F4608000331088880016F47040000000121063739393933303D2804DAD95F5C492C4C20E222019D8DFA4209A9FF0E1888486DA30B3069000000000000000063F9D0394138434230313442";
//		String res="00831F31000142011F4302823644072016070112563145071467359008777F4608000331088880016F47040000000148038888885F08000331088880016F6004000000013C304E4D3036C3CFCFE9CFE9494431383337313532343139393031303130303531584D504E313131333136323735373732393939353845323741";
		//String res = "009A600013000034303030000442011F43028236440720160415102054450820150604000001954608000331088880016F4704000000014803888888510A6013820800092270881F5E0820150604000001955F08000331088880016F6004000000013C304E4D3036E996B8E68E93C991E5A6BEE4BB8BE5BCB6E9949FE7B5804431383331303232373139383030373136303431313636434434393931";
		//String res = "00696000130000343030300004000230300108BDBBD2D7B3C9B9A6020131030438323336440720160417091002450817041502003217324608000331088880016F47040000000151091E103137303431353032303033323137333221063739393935363139373839343742";
		String res="020131030438323336440312460145014F4608000331088880022F4704000000010806383838383838510862250000000000145E014F5F08000331088880022F6004000000013C1F494431383333313038313139393230343031313233344E4D3034D5C5C8FD";
		byte[] response = BitConvert.Str2Hex(res);
		//System.out.println(new String(response,"GBK"));
		System.out.println(msg.getMsgMapRes());
		msg.parseResponseByte(response, false);
		TLV info = msg.getMsgMapRes().get(1);
		
		String ret = new String(info.getValuebytes(), "GBK");
		System.out.println("retinfo:" + info.getValue());
		System.out.println("ret:" + ret);
		
		TLV macInfo = msg.getMsgMapRes().get(61);
		String macKey = macInfo.getMacKey();
		System.out.println("MACKEY:" + macKey);
		System.out.println(msg.getMacValue());
		
		HashMap<Integer, TLV> map = msg.getMsgMapRes();
		for (Map.Entry<Integer, TLV> entry : map.entrySet()) {
			System.out.println("tag=" + entry.getValue().getTag() + ", value=" + entry.getValue().getValue());
		}
	}
}
